package dbexp.model;

import static dbexp.model.db.DbOT.COLUMN;
import static dbexp.model.db.DbOT.ERROR;
import static dbexp.model.db.DbOT.EXCEPTION;
import static dbexp.model.db.DbOT.FUNCTION;
import static dbexp.model.db.DbOT.NONE;
import static dbexp.model.db.DbOT.NULL;
import static dbexp.model.db.DbOT.OBJECT_PRIVILEGE;
import static dbexp.model.db.DbOT.OBJECT_TYPE;
import static dbexp.model.db.DbOT.PACKAGE;
import static dbexp.model.db.DbOT.PACKAGEBODY;
import static dbexp.model.db.DbOT.PROCEDURE;
import static dbexp.model.db.DbOT.ROLE;
import static dbexp.model.db.DbOT.SCHEMA;
import static dbexp.model.db.DbOT.SECURITY;
import static dbexp.model.db.DbOT.SEQUENCE;
import static dbexp.model.db.DbOT.SYNONYM;
import static dbexp.model.db.DbOT.SOURCE_TYPE;
import static dbexp.model.db.DbOT.SYSTEM_PRIVILEGE;
import static dbexp.model.db.DbOT.TABLE;
import static dbexp.model.db.DbOT.TABLESPACE;
import static dbexp.model.db.DbOT.TRIGGER;
import static dbexp.model.db.DbOT.UNKNOWN;
import static dbexp.model.db.DbOT.USER;
import static dbexp.model.db.DbOT.VIEW;
import static dbexp.model.db.DbOT.INDEX;

import java.io.Serializable;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class DbObject implements Serializable {
	transient private static final long serialVersionUID = 1L;
	protected RpcMap map;
	protected int type = UNKNOWN;
	protected String name = "";
	protected String schema = "";
	protected String query = "";
	protected String extEnd = "";
	protected String validIcon = "file-txt";
	protected String invalidIcon = "invalid-icon";
	protected String categoriesIcon = "folder-database-icon";

	public DbObject() {
	}

	public DbObject(String name) {
		setName(name);
	}

	public DbObject(String name, int typ) {
		setName(name);
		setTyp(typ);
	}

	public DbObject(String name, String schema) {
		setName(name);
		setSchema(schema);
	}

	public DbObject(String name, String schema, int typ) {
		setName(name);
		setSchema(schema);
		setTyp(typ);
	}

	public DbObject(Map<String, Object> prop) {
		super();
		setProp(prop);
	}

	public String getIcon() {
		if (isValid()) {
			return validIcon;
		} else {
			return invalidIcon;
		}
	}

	public String getValidIcon() {
		return validIcon;
	}

	public String getInvalidIcon() {
		return invalidIcon;
	}

	public String getCategoriesIcon() {
		return categoriesIcon;
	}

	public void setIcons(String icon) {
		setIcons(icon, icon);
	}

	public void setIcons(String valid, String category) {
		this.validIcon = (valid);
		this.categoriesIcon = (category);
	}

	public boolean isValid() {
		return is("v", true);
	}

	public void setValid(boolean valid) {
		set("v", valid);
	}

	public void setTyp(final int t) {
		type = t;
	}

	public final int getType() {
		return type;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getSchema() {
		return schema;
	}

	public void setSchema(String schema) {
		this.schema = schema;
		set("schema", schema);
	}

	@Override
	public boolean equals(Object obj) {
		if (obj instanceof DbObject) {
			return ((DbObject) obj).getName().equals(getName());
		}
		if (obj instanceof String) {
			return obj.equals(getName());
		}
		return false;
	}

	public void setExtEnd(String ext) {
		this.extEnd = ext;
	}

	public String getExtEnt() {
		return this.extEnd;
	}

	@SuppressWarnings("unchecked")
	public <O> O get(String property) {
		return map == null ? null : (O) map.get(property);
	}

	public boolean isNotNull(String property) {
		return !isNull(property);
	}

	public boolean isNull(String property) {
		return map == null ? true : (map.get(property) == null);
	}

	public boolean isNotNullString(String property) {
		return !isNullString(property);
	}

	public boolean isNullString(String property) {
		return map == null ? true : (getString(property) == null || getString(
				property).trim().length() == 0);
	}

	public boolean is(String property) {
		return is(property, false);
	}

	public boolean is(String property, boolean defValue) {
		return map == null || map.get(property) == null ? defValue
				: ((Boolean) map.get(property)).booleanValue();
	}

	@SuppressWarnings("unchecked")
	public <O> O get(String property, O Null) {
		O value = (O) get(property);
		return (value == null) ? Null : value;
	}

	public String getString(String property) {
		return map == null ? null
				: (map.get(property) instanceof String) ? (String) map
						.get(property) : null;
	}

	public String getNNString(String property) {
		return getNNString(property, "");
	}

	public String getNNString(String property, String def) {
		return map == null || map.get(property) == null ? def : (map
				.get(property) instanceof String) ? (String) map.get(property)
				: def;
	}

	public int getInt(String property) {
		return getInt(property, 0);
	}

	public int getInt(String property, int def) {
		return map == null || get(property) == null
				|| !(get(property) instanceof Integer) ? def
				: ((Integer) get(property)).intValue();
	}

	public long getLong(String property) {
		return getLong(property, 0);
	}

	public long getLong(String property, long def) {
		return map == null || get(property) == null
				|| !(get(property) instanceof Long) ? def
				: ((Long) get(property)).longValue();
	}

	public double getDouble(String property) {
		return getDouble(property, 0.0);
	}

	public double getDouble(String property, double def) {
		return map == null || get(property) == null
				|| !(get(property) instanceof Double) ? def
				: ((Double) get(property)).doubleValue();
	}

	public Map<String, Object> getProp() {
		HashMap<String, Object> newMap = new HashMap<String, Object>();
		if (map != null) {
			newMap.putAll(map);
		}
		return newMap;
	}

	public Collection<String> getPropertyNames() {
		Set<String> set = new HashSet<String>();
		if (map != null) {
			if (name != null) {
				map.put("n", name);
			}
			map.put("t", new Integer(type));
			set.addAll(map.keySet());
		}
		return set;
	}

	@Override
	public int hashCode() {
		if (map != null) {
			return map.hashCode();
		}
		return super.hashCode();
	}

	@SuppressWarnings("unchecked")
	public <O> O remove(String property) {
		return map == null ? null : (O) map.remove(property);
	}

	@SuppressWarnings("unchecked")
	public <O> O set(String property, O value) {
		if (map == null) {
			map = new RpcMap();
		}
		return (O) map.put(property, value);
	}

	public Integer set(String property, int value) {
		if (map == null) {
			map = new RpcMap();
		}
		return (Integer) map.put(property, new Integer(value));
	}

	public Long set(String property, long value) {
		if (map == null) {
			map = new RpcMap();
		}
		return (Long) map.put(property, new Long(value));
	}

	public Double set(String property, double value) {
		if (map == null) {
			map = new RpcMap();
		}
		return (Double) map.put(property, new Double(value));
	}

	public Boolean set(String property, boolean value) {
		if (map == null) {
			map = new RpcMap();
		}
		return (Boolean) map.put(property, new Boolean(value));
	}

	public void setBoolean(String property, String value) {
		if (map == null) {
			map = new RpcMap();
		}
		String sV = (value == null) ? "" : value.trim().toUpperCase();
		boolean settingValue = false;
		if (sV.equals("TRUE")) {
			settingValue = true;
		} else if (sV.equals("FALSE")) {
			settingValue = false;
		} else if (sV.equals("T")) {
			settingValue = true;
		} else if (sV.equals("N")) {
			settingValue = false;
		} else if (sV.equals("Y")) {
			settingValue = true;
		}
		set(property, new Boolean(settingValue));
	}

	public void setProp(Map<String, Object> prop) {
		for (String proper : prop.keySet()) {
			set(proper, prop.get(proper));
		}
	}

	public boolean isTable() {
		return (type == TABLE);
	}

	public boolean isError() {
		return (type == ERROR);
	}

	public boolean isFunction() {
		return (type == FUNCTION);
	}

	public boolean isObjectType() {
		return (type == OBJECT_TYPE);
	}

	public boolean isPackage() {
		return (type == PACKAGE);
	}

	public boolean isPackagebody() {
		return (type == PACKAGEBODY);
	}

	public boolean isSource() {
		return (isFunction() || isPackage() || isPackagebody() || isProcedure() || (type == SOURCE_TYPE));
	}

	public boolean isObjectPrivilege() {
		return (type == OBJECT_PRIVILEGE);
	}

	public boolean isSystemPrivilege() {
		return (type == SYSTEM_PRIVILEGE);
	}

	public boolean isProcedure() {
		return (type == PROCEDURE);
	}

	public boolean isRole() {
		return (type == ROLE);
	}

	public boolean isSchema() {
		return (type == SCHEMA);
	}

	public boolean isSecurity() {
		return (type == SECURITY);
	}

	public boolean isSequence() {
		return (type == SEQUENCE);
	}

	public boolean isSynonim() {
		return (type == SYNONYM) ? true : false;
	}

	public boolean isTablespace() {
		return (type == TABLESPACE) ? true : false;
	}

	public boolean isTrigger() {
		return (type == TRIGGER) ? true : false;
	}

	public boolean isUser() {
		return (type == USER) ? true : false;
	}

	public boolean isView() {
		return (type == VIEW) ? true : false;
	}

	public boolean isColumn() {
		return (type == COLUMN) ? true : false;
	}

	public boolean isException() {
		return (type == EXCEPTION) ? true : false;
	}

	public boolean isIndex() {
		return (type == INDEX) ? true : false;
	}

	public boolean isUnknown() {
		return (type == UNKNOWN || type == NONE || type == NULL) ? true : false;
	}

	public void setInfo(String info) {
		set("info", info);
	}

	public String getInfo() {
		return getNNString("info");
	}

	@Override
	public String toString() {
		return getName();
	}

	public Object parseInt(String i, String ifIsNull) {
		if (ifIsNull != null && ifIsNull.equals(i)) {
			return i;
		} else {
			try {
				int x = Integer.parseInt(i);
				return new Integer(x);
			} catch (NumberFormatException nfe) {
				if (ifIsNull != null) {
					return ifIsNull;
				}
			}
		}
		return null;
	}

	public String printContent() {
		String out = "";
		Iterator<String> it = getPropertyNames().iterator();
		while (it.hasNext()) {
			String key = it.next();
			out += ("key:" + key + ",value:" + get(key)) + "\n";
		}
		return out;
	}

	public String oneFromDual() {
		return "SELECT 1 FROM DUAL";
	}

	public String getObjectNameForQuery() {
		return "\"" + getSchema() + "\".\"" + getName() + "\"";
	}

	public String getError() {
		return getString("error");
	}

	public boolean requiredFieldIsNotNull() {
		if (getName() != null && !getName().equals("NOTFOUND")
				&& getSchema() != null) {
			return true;
		} else {
			return false;
		}
	}

	public String getQuery(int operation) {
		return oneFromDual();
	}

	public static final int ALTER = 0x000012;
	public static final int SELECT = 0x000013;
	public static final int CREATE = 0x000014;
	public static final int DELETE = 0x000015;
	public static final int EXECUTE = 0x000016;
	public static final int DROP_COLUMN = 0x000019;
	public static final int ADD_COLUMN = 0x000020;
	public static final int ALTER_COLUMN = 0x000021;
	public static final int INSERT_RECORD = 0x000022;
	public static final int UPDATE_RECORD = 0x000023;
	public static final int DELETE_RECORD = 0x000024;
}
